#include "predict_evaluation.h"

void init_predict_evaluation(predict_evaluation_t* predict_evaluation){
    //申请一个头部的空间
    predict_evaluation->history_head = (history_unit_t *)malloc(sizeof(history_unit_t));

    //将双向链表头指针初始化
    memset(predict_evaluation->history_head, 0, sizeof(history_unit_t));

    //将链表头结点打结
    predict_evaluation->history_head->next = predict_evaluation->history_head;
    predict_evaluation->history_head->prev = predict_evaluation->history_head;

    //将剩下的属性初始化
    predict_evaluation->history_size = 0;
    predict_evaluation->history_count = 0;
    predict_evaluation->err_count = 0;
}

void insert_predict_history(predict_evaluation_t* predict_evaluation, long predict_block){
    //将新的预测节点写入预测历史，写在链表的头部
    history_unit_t* head_next = predict_evaluation->history_head->next;

    //创建一个新的节点，存储预测历史
    history_unit_t* new_history = (history_unit_t *)malloc(sizeof(history_unit_t));

    memset(new_history, 0, sizeof(history_unit_t));

    //记录当前访问节点
    new_history->access_block = predict_block;

    //将节点插入到历史中
    predict_evaluation->history_head->next = new_history;
    new_history->prev = predict_evaluation->history_head;

    new_history->next = head_next;
    head_next->prev = new_history;

    //更新历史记录的大小
    predict_evaluation->history_size++;

    //当占满之后淘汰节点
    if(predict_evaluation->history_size > MAX_HISTORY_DEEP){
        history_unit_t* end = predict_evaluation->history_head->prev;
        
        //更新淘汰节点的个数
        predict_evaluation->history_count++;

        //更新错误预测节点的个数
        if(end->is_accessed == 0){
            predict_evaluation->err_count++;   
        }

        //将旧的节点淘汰
        predict_evaluation->history_size--;

        //将指针缝合
        end->next->prev = end->prev;
        end->prev->next = end->next;

        //将节点析构
        free(end);
    }
}

void update_predict_evaluation(predict_evaluation_t* predict_evaluation, long now_access){
    //遍历所有的节点，将当前访问的节点标记
    history_unit_t* scan = predict_evaluation->history_head->next;

    while(scan != predict_evaluation->history_head){
        
        if(scan->access_block == now_access){
            scan->is_accessed = 1;
        }
        scan = scan->next;
    }
}